package com.pan.download4.ctrl;

import com.pan.entity.Chapter;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

public class TaskPublishSynchronized {

    private LinkedList<Chapter> workList;
    private int intervalTime;
    private ReentrantLock listLock;

    {
        listLock = new ReentrantLock();
    }
    public TaskPublishSynchronized(Collection<Chapter> workList){
        this(workList,0);
    }

    public TaskPublishSynchronized(LinkedList<Chapter> workList,int intervalTime) {
        this.workList = workList;
        this.intervalTime = intervalTime;
    }
    public TaskPublishSynchronized(Collection<Chapter> workList,int intervalTime) {
        this.workList = new LinkedList<>();
        this.workList.addAll(workList);
        this.intervalTime = intervalTime;
    }

    public Chapter getTask(){
        listLock.lock();
        Chapter work = workList.pollFirst();
        if (intervalTime>0){
            try {
                Thread.sleep(intervalTime+(int)(Math.random()*500));
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        listLock.unlock();
        return work;
    }



    public void cancelTask(Chapter chapter) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, InstantiationException {
        listLock.lock();
        Class<LinkedList> linkedListClass = LinkedList.class;
        Field firstField = linkedListClass.getDeclaredField("first");
        firstField.setAccessible(true);
        Field lastField = linkedListClass.getDeclaredField("last");
        lastField.setAccessible(true);
        Field sizeField =  linkedListClass.getDeclaredField("size");
        sizeField.setAccessible(true);
        Object node = firstField.get(workList);
        Class nodeClass = Class.forName("java.util.LinkedList$Node");
        Constructor nodeConstructor = nodeClass.getDeclaredConstructors()[0];
        nodeConstructor.setAccessible(true);
        Field itemField = nodeClass.getDeclaredField("item");
        itemField.setAccessible(true);
        Field nextField = nodeClass.getDeclaredField("next");
        nextField.setAccessible(true);
        Field prevField = nodeClass.getDeclaredField("prev");
        prevField.setAccessible(true);
        if (node == null){
            Object newNode = nodeConstructor.newInstance(null,chapter,null);
            firstField.set(workList,newNode);
            lastField.set(workList,newNode);
            sizeField.set(workList,1);
            return;
        }
        for(;;) {
            Object prevNode = prevField.get(node);
            Chapter c = (Chapter) itemField.get(node);
            Object nextNode = nextField.get(node);
            if (c.getOrderNumber() > chapter.getOrderNumber()) {
                Object newNode = nodeConstructor.newInstance(prevNode,chapter,node);
                if (prevNode != null) {
                    nextField.set(prevNode, newNode);
                }else {
                    firstField.set(workList,newNode);
                }
                break;
            } else if (c.getOrderNumber() == chapter.getOrderNumber()) {
//                throw new RuntimeException("该任务已经存在");
                listLock.unlock();
                return;
            } else if (nextNode == null) {
                Object newNode = nodeConstructor.newInstance(node,chapter,null);
                nextField.set(node,newNode);
                lastField.set(workList,newNode);
                break;
            }
            node = nextNode;
        }
        sizeField.set(workList,workList.size()+1);
        listLock.unlock();
        return;
    }


}
